package com.allwees.bs.core.model.logistics.dto;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.allwees.core.common.util.json.JsonUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 物流详情
 *
 * @author yangylsky
 * @since 2019-10-10
 *
 */
@Data
@Accessors(chain = true)
public class TrackingDetail implements Serializable {

	public static final String EXPRESS_NOT_FOUND = "notfound";

	public static final String STATUS_DELIVERED = "delivered";

	/**
	 * 物流同步元数据[code]，200 - 正常
	 */
	private Integer metaCode;

	/**
	 * 物流同步元数据[type]，"Success" - 正常
	 */
	private String metaType;

	/**
	 * 物流同步元数据[message]，"Success" - 正常
	 */
	private String metaMessage;

	/**
	 * 物流商代号，示例: "yanwen"
	 */
	private String carrierCode;

	/**
	 * 运单号，示例: "75164785678930"
	 */
	private String expressCode;

	/**
	 * 当前状态，示例: "delivered"，"pickup"，"transit"，"notfound"
	 */
	private String status;

	/**
	 * 从发货到签收，中间过程持续的天数（如果一直未签收，则显示从发货到当前时间的天数）
	 */
	private Integer itemTimeLength;

	/**
	 * 最后一个事件描述，示例: "【杭州市】  已签收, 签收人凭取货码签收, 如有疑问请电联: 18357191931 ..."
	 */
	private String lastEvent;

	/**
	 * 揽收时间
	 */
	private Date itemReceived;

	/**
	 * 最后更新时间
	 */
	private Date lastUpdateTime;

	/**
	 * 物流跟踪详情
	 */
	private List<TrackingDetailItem> items;

	public boolean normalMetaCode() {
		return (metaCode != null && metaCode == HttpStatus.SC_OK);
	}

	public boolean normalTrackingDetail() {
		return normalMetaCode() && !EXPRESS_NOT_FOUND.equalsIgnoreCase(status);
	}

	@JsonIgnore
	public boolean isDelivered() {
		return normalTrackingDetail() && STATUS_DELIVERED.equalsIgnoreCase(status);
	}

	@JsonIgnore
	public Date getDeliverDate() {
		if(items != null) {
			for(TrackingDetailItem item : items) {
				if(STATUS_DELIVERED.equalsIgnoreCase(item.getCheckPointStatus())) {
					return item.getDate();
				}
			}
		}
		return null;
	}

	/**
	 * 从JSON解析，格式见: \src\test\resources\com\allwees\module\logistics\model\*.json
	 *
	 * @param json
	 * @return
	 */
	public static TrackingDetail fromJson(String json) {
		if(StringUtils.isBlank(json)) {
			return null;
		}
		JSONObject trackingDetailObj = JsonUtil.toJSONObject(json);
		JSONObject meta = trackingDetailObj.getJSONObject("meta");
		TrackingDetail trackingDetail = new TrackingDetail();

		trackingDetail.setMetaCode(meta.getInteger("code"))
				.setMetaType(meta.getString("type"))
				.setMetaMessage(meta.getString("message"));
		if(trackingDetail.metaCode == HttpStatus.SC_OK) {
			JSONObject detailsObj = trackingDetailObj.getJSONObject("data").getJSONArray("items").getJSONObject(0);
			JSONObject destinationInfo = detailsObj.getJSONObject("destination_info");

			if (destinationInfo != null && destinationInfo.getJSONObject("trackinfo") != null){
				trackingDetail = parseTrackingDetail(detailsObj, destinationInfo, trackingDetail);
			} else {
				trackingDetail = parseTrackingDetail(detailsObj, detailsObj.getJSONObject("origin_info"), trackingDetail);
			}
		}
		return trackingDetail;
	}

	private static TrackingDetail parseTrackingDetail(JSONObject detailsObj, JSONObject originInfo, TrackingDetail trackingDetail) {
		JSONArray trackInfo = originInfo == null ? null : originInfo.getJSONArray("trackinfo");
		return trackingDetail.setCarrierCode(detailsObj.getString("carrier_code"))
				.setExpressCode(detailsObj.getString("tracking_number"))
				.setStatus(detailsObj.getString("status"))
				.setExpressCode(detailsObj.getString("tracking_number"))
				.setItemTimeLength(detailsObj.getInteger("itemTimeLength"))
				.setLastEvent(detailsObj.getString("lastEvent"))
				.setItemReceived(originInfo.getDate("ItemReceived"))
				.setLastUpdateTime(detailsObj.getDate("lastUpdateTime"))
				.setItems(parseTrackingDetailItems(trackInfo));
	}

	private static List<TrackingDetailItem> parseTrackingDetailItems(JSONArray trackInfo) {
		if(trackInfo == null) {
			return new ArrayList<>();
		}
		List<TrackingDetailItem> items = new ArrayList<>(trackInfo.size());
		trackInfo.forEach(trackInfoItem -> {
				JSONObject trackItemObj = (JSONObject) trackInfoItem;
				TrackingDetailItem item = new TrackingDetailItem()
					 .setDate(trackItemObj.getDate("Date"))
					 .setStatusDescription(trackItemObj.getString("StatusDescription"))
					 .setDetails(trackItemObj.getString("Details"))
					 .setCheckPointStatus(trackItemObj.getString("checkpoint_status"));

				items.add(item);
			});
		return items;
	}
}
